/*     */ package com.zimbra.cs.service.mail;
/*     */ 
/*     */ import com.zimbra.client.ZMailbox;
/*     */ import com.zimbra.client.ZMailbox.Options;
/*     */ import com.zimbra.common.account.Key.AccountBy;
/*     */ import com.zimbra.common.auth.ZAuthToken;
/*     */ import com.zimbra.common.calendar.ZCalendar.ICalTok;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZCalendarBuilder;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZComponent;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZParameter;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZProperty;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZVCalendar;
/*     */ import com.zimbra.common.mime.ContentType;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.soap.Element;
/*     */ import com.zimbra.common.soap.MailConstants;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LogFactory;
/*     */ import com.zimbra.common.util.Pair;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.common.zmime.ZMimeMessage;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.account.AuthToken;
/*     */ import com.zimbra.cs.account.Provisioning;
/*     */ import com.zimbra.cs.mailbox.CalendarItem;
/*     */ import com.zimbra.cs.mailbox.MailItem.Type;
/*     */ import com.zimbra.cs.mailbox.MailSender;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.MailboxLock;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.mailbox.Message;
/*     */ import com.zimbra.cs.mailbox.OperationContext;
/*     */ import com.zimbra.cs.mailbox.calendar.CalendarDataSource;
/*     */ import com.zimbra.cs.mailbox.calendar.CalendarMailSender;
/*     */ import com.zimbra.cs.mailbox.calendar.Invite;
/*     */ import com.zimbra.cs.mailbox.calendar.RecurId;
/*     */ import com.zimbra.cs.mailbox.calendar.ZOrganizer;
/*     */ import com.zimbra.cs.mime.Mime;
/*     */ import com.zimbra.cs.mime.MimeVisitor;
/*     */ import com.zimbra.cs.mime.MimeVisitor.ModificationCallback;
/*     */ import com.zimbra.cs.mime.MimeVisitor.VisitPhase;
/*     */ import com.zimbra.cs.service.FileUploadServlet;
/*     */ import com.zimbra.cs.service.FileUploadServlet.Upload;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import com.zimbra.cs.service.util.ItemIdFormatter;
/*     */ import com.zimbra.cs.util.AccountUtil;
/*     */ import com.zimbra.cs.util.JMSession;
/*     */ import com.zimbra.soap.ZimbraSoapContext;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.util.ArrayList;
/*     */ import java.util.HashMap;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import javax.activation.DataHandler;
/*     */ import javax.activation.DataSource;
/*     */ import javax.mail.Address;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.Session;
/*     */ import javax.mail.internet.InternetAddress;
/*     */ import javax.mail.internet.MimeBodyPart;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.mail.internet.MimeMultipart;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public final class SendMsg
/*     */   extends MailDocumentHandler
/*     */ {
/*  90 */   private static final Log LOG = LogFactory.getLog(SendMsg.class);
/*     */   
/*  92 */   private static enum SendState { NEW,  SENT,  PENDING;
/*     */     
/*     */     private SendState() {} }
/*     */   
/*     */   private static final long MAX_IN_FLIGHT_DELAY_MSECS = 4000L;
/*  97 */   private static final long RETRY_CHECK_PERIOD_MSECS = 500L; private static final ItemId NO_MESSAGE_SAVED_TO_SENT = new ItemId((String)null, -1);
/*     */   
/*     */   public Element handle(Element request, Map<String, Object> context) throws ServiceException
/*     */   {
/* 101 */     ZimbraSoapContext zsc = getZimbraSoapContext(context);
/* 102 */     Mailbox mbox = getRequestedMailbox(zsc);
/* 103 */     AccountUtil.checkQuotaWhenSendMail(mbox);
/*     */     
/* 105 */     OperationContext octxt = getOperationContext(zsc, context);
/* 106 */     ItemIdFormatter ifmt = new ItemIdFormatter(zsc);
/*     */     
/*     */ 
/* 109 */     Element msgElem = request.getElement("m");
/*     */     
/*     */ 
/* 112 */     String attachId = msgElem.getAttribute("aid", null);
/*     */     
/* 114 */     boolean needCalendarSentByFixup = request.getAttributeBool("needCalendarSentByFixup", false);
/* 115 */     boolean isCalendarForward = request.getAttributeBool("isCalendarForward", false);
/* 116 */     boolean noSaveToSent = request.getAttributeBool("noSave", false);
/*     */     
/* 118 */     String origId = msgElem.getAttribute("origid", null);
/* 119 */     ItemId iidOrigId = origId == null ? null : new ItemId(origId, zsc);
/* 120 */     String replyType = msgElem.getAttribute("rt", MailSender.MSGTYPE_REPLY);
/* 121 */     String identityId = msgElem.getAttribute("idnt", null);
/* 122 */     String draftId = msgElem.getAttribute("did", null);
/* 123 */     ItemId iidDraft = draftId == null ? null : new ItemId(draftId, zsc);
/* 124 */     boolean sendFromDraft = msgElem.getAttributeBool("sfd", false);
/*     */     
/* 126 */     SendState state = SendState.NEW;
/* 127 */     ItemId savedMsgId = null;
/* 128 */     Pair<String, ItemId> sendRecord = null;
/*     */     
/*     */ 
/* 131 */     String sendUid = request.getAttribute("suid", null);
/* 132 */     if (sendUid != null) {
/* 133 */       long delay = 4000L;
/*     */       do {
/* 135 */         if (state == SendState.PENDING) {
/*     */           try {
/* 137 */             delay -= 500L;
/* 138 */             Thread.sleep(500L);
/*     */           }
/*     */           catch (InterruptedException ie) {}
/*     */         }
/* 142 */         Pair<SendState, Pair<String, ItemId>> result = findPendingSend(Integer.valueOf(mbox.getId()), sendUid);
/* 143 */         state = (SendState)result.getFirst();
/* 144 */         sendRecord = (Pair)result.getSecond();
/* 145 */       } while ((state == SendState.PENDING) && (delay >= 0L));
/*     */     }
/*     */     
/* 148 */     if (state == SendState.SENT)
/*     */     {
/* 150 */       savedMsgId = (ItemId)sendRecord.getSecond();
/* 151 */     } else { if (state == SendState.PENDING)
/*     */       {
/* 153 */         throw MailServiceException.TRY_AGAIN("message send already in progress: " + sendUid); }
/* 154 */       if (state == SendState.NEW) {
/* 155 */         ParseMimeMessage.MimeMessageData mimeData = new ParseMimeMessage.MimeMessageData();
/*     */         try {
/*     */           MimeMessage mm;
/*     */           MimeMessage mm;
/* 159 */           if (attachId != null) {
/* 160 */             mm = parseUploadedMessage(zsc, attachId, mimeData, needCalendarSentByFixup); } else { MimeMessage mm;
/* 161 */             if ((iidDraft != null) && (sendFromDraft)) {
/* 162 */               Message msg = mbox.getMessageById(octxt, iidDraft.getId());
/* 163 */               mm = msg.getMimeMessage(false);
/*     */             } else {
/* 165 */               mm = ParseMimeMessage.parseMimeMsgSoap(zsc, octxt, mbox, msgElem, null, mimeData);
/*     */             }
/*     */           }
/* 168 */           savedMsgId = doSendMessage(octxt, mbox, mm, mimeData.uploads, iidOrigId, replyType, identityId, noSaveToSent, needCalendarSentByFixup, isCalendarForward);
/*     */           
/*     */ 
/*     */ 
/*     */ 
/* 173 */           if (savedMsgId == null) {
/* 174 */             savedMsgId = NO_MESSAGE_SAVED_TO_SENT;
/*     */           }
/*     */           
/*     */ 
/* 178 */           if (sendRecord != null) {
/* 179 */             sendRecord.setSecond(savedMsgId);
/*     */           }
/*     */         } catch (ServiceException e) {
/* 182 */           clearPendingSend(Integer.valueOf(mbox.getId()), sendRecord);
/* 183 */           throw e;
/*     */         } catch (RuntimeException re) {
/* 185 */           clearPendingSend(Integer.valueOf(mbox.getId()), sendRecord);
/* 186 */           throw re;
/*     */         }
/*     */         finally {
/* 189 */           if (mimeData.fetches != null) {
/* 190 */             FileUploadServlet.deleteUploads(mimeData.fetches);
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/* 195 */     if (iidDraft != null) {
/* 196 */       deleteDraft(iidDraft, octxt, mbox, zsc);
/*     */     }
/*     */     
/* 199 */     Element response = zsc.createElement(MailConstants.SEND_MSG_RESPONSE);
/* 200 */     Element respElement = response.addElement("m");
/* 201 */     if ((savedMsgId != null) && (savedMsgId != NO_MESSAGE_SAVED_TO_SENT) && (savedMsgId.getId() > 0)) {
/* 202 */       respElement.addAttribute("id", ifmt.formatItemId(savedMsgId));
/*     */     }
/* 204 */     return response;
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public static ItemId doSendMessage(OperationContext oc, Mailbox mbox, MimeMessage mm, List<FileUploadServlet.Upload> uploads, ItemId origMsgId, String replyType, String identityId, boolean noSaveToSent, boolean needCalendarSentByFixup, boolean isCalendarForward)
/*     */     throws ServiceException
/*     */   {
/* 212 */     boolean isCalendarMessage = false;
/*     */     
/* 214 */     OutlookICalendarFixupMimeVisitor mv = null;
/* 215 */     if ((needCalendarSentByFixup) || (isCalendarForward)) {
/* 216 */       mv = new OutlookICalendarFixupMimeVisitor(mbox.getAccount(), mbox).needFixup(needCalendarSentByFixup).setIsCalendarForward(isCalendarForward);
/*     */       
/*     */       try
/*     */       {
/* 220 */         mv.accept(mm);
/*     */       } catch (MessagingException e) {
/* 222 */         throw ServiceException.PARSE_ERROR("Error while fixing up SendMsg for SENT-BY", e);
/*     */       }
/* 224 */       isCalendarMessage = mv.isCalendarMessage();
/*     */     }
/*     */     MailSender sender;
/*     */     MailSender sender;
/* 228 */     if (isCalendarMessage) {
/* 229 */       sender = CalendarMailSender.getCalendarMailSender(mbox);
/*     */     } else
/* 231 */       sender = mbox.getMailSender();
/*     */     ItemId id;
/* 233 */     ItemId id; if (noSaveToSent) {
/* 234 */       id = sender.sendMimeMessage(oc, mbox, Boolean.valueOf(false), mm, uploads, origMsgId, replyType, null, false);
/*     */     } else {
/* 236 */       id = sender.sendMimeMessage(oc, mbox, mm, uploads, origMsgId, replyType, identityId, false);
/*     */     }
/*     */     try
/*     */     {
/* 240 */       if ((isCalendarMessage) && (isCalendarForward) && (mv.getOriginalInvite() != null)) {
/* 241 */         ZOrganizer org = mv.getOriginalInvite().getOrganizer();
/* 242 */         if (org != null) {
/* 243 */           String orgAddress = org.getAddress();
/* 244 */           Account orgAccount = Provisioning.getInstance().getAccountByName(orgAddress);
/* 245 */           if ((orgAccount != null) && (!orgAccount.getId().equals(mbox.getAccount().getId()))) {
/* 246 */             MimeMessage notifyMimeMsg = CalendarMailSender.createForwardNotifyMessage(mbox.getAccount(), orgAccount, orgAddress, mm.getAllRecipients(), mv.getOriginalInvite());
/*     */             
/* 248 */             CalendarMailSender.sendPartial(oc, mbox, notifyMimeMsg, null, null, null, null, false, true);
/*     */           }
/*     */         }
/*     */       }
/*     */     } catch (Exception e) {
/* 253 */       ZimbraLog.soap.warn("Ignoring error while sending Calendar Invitation Forward Notification", e);
/*     */     }
/*     */     
/* 256 */     return id;
/*     */   }
/*     */   
/*     */   static MimeMessage parseUploadedMessage(ZimbraSoapContext zsc, String attachId, ParseMimeMessage.MimeMessageData mimeData) throws ServiceException {
/* 260 */     return parseUploadedMessage(zsc, attachId, mimeData, false);
/*     */   }
/*     */   
/*     */   static MimeMessage parseUploadedMessage(ZimbraSoapContext zsc, String attachId, ParseMimeMessage.MimeMessageData mimeData, boolean needCalendarSentByFixup)
/*     */     throws ServiceException
/*     */   {
/* 266 */     boolean anySystemMutators = MimeVisitor.anyMutatorsRegistered();
/*     */     
/* 268 */     FileUploadServlet.Upload up = FileUploadServlet.fetchUpload(zsc.getAuthtokenAccountId(), attachId, zsc.getAuthToken());
/* 269 */     if (up == null) {
/* 270 */       throw MailServiceException.NO_SUCH_UPLOAD(attachId);
/*     */     }
/* 272 */     (mimeData.uploads = new ArrayList(1)).add(up);
/*     */     try
/*     */     {
/* 275 */       if ((anySystemMutators) || (needCalendarSentByFixup)) {
/* 276 */         MimeMessage mm = new ZMimeMessage(JMSession.getSession(), up.getInputStream());
/* 277 */         if (anySystemMutators) {
/* 278 */           return mm;
/*     */         }
/*     */         
/* 281 */         SendMsg.OutlookICalendarFixupMimeVisitor.ICalendarModificationCallback callback = new SendMsg.OutlookICalendarFixupMimeVisitor.ICalendarModificationCallback();
/* 282 */         MimeVisitor mv = new OutlookICalendarFixupMimeVisitor(getRequestedAccount(zsc), getRequestedMailbox(zsc)).needFixup(true).setCallback(callback);
/*     */         try {
/* 284 */           mv.accept(mm);
/*     */         } catch (MessagingException e) {}
/* 286 */         if (callback.wouldCauseModification()) {
/* 287 */           return mm;
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 292 */       new ZMimeMessage(JMSession.getSession(), up.getInputStream())
/*     */       {
/*     */         protected void updateHeaders() throws MessagingException {
/* 295 */           setHeader("MIME-Version", "1.0");
/* 296 */           if (getMessageID() == null)
/* 297 */             updateMessageID();
/*     */         }
/*     */       };
/*     */     } catch (MessagingException e) {
/* 301 */       throw MailServiceException.MESSAGE_PARSE_ERROR(e);
/*     */     } catch (IOException e) {
/* 303 */       throw ServiceException.FAILURE("IOException when parsing upload", e);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/* 308 */   private static final Map<Integer, List<Pair<String, ItemId>>> sSentTokens = new HashMap(100);
/*     */   private static final int MAX_SEND_UID_CACHE = 5;
/*     */   
/*     */   private static Pair<SendState, Pair<String, ItemId>> findPendingSend(Integer mailboxId, String sendUid) {
/* 312 */     SendState state = SendState.NEW;
/* 313 */     Pair<String, ItemId> sendRecord = null;
/*     */     
/* 315 */     synchronized (sSentTokens) {
/* 316 */       List<Pair<String, ItemId>> sendData = (List)sSentTokens.get(mailboxId);
/* 317 */       if (sendData == null) {
/* 318 */         sSentTokens.put(mailboxId, sendData = new ArrayList(5));
/*     */       }
/*     */       
/* 321 */       for (Pair<String, ItemId> record : sendData) {
/* 322 */         if (((String)record.getFirst()).equals(sendUid)) {
/* 323 */           state = record.getSecond() == null ? SendState.PENDING : SendState.SENT;
/* 324 */           sendRecord = record;
/* 325 */           break;
/*     */         }
/*     */       }
/*     */       
/* 329 */       if (state == SendState.NEW) {
/* 330 */         if (sendData.size() >= 5) {
/* 331 */           sendData.remove(0);
/*     */         }
/* 333 */         sendRecord = new Pair(sendUid, null);
/* 334 */         sendData.add(sendRecord);
/*     */       }
/*     */     }
/*     */     
/* 338 */     return new Pair(state, sendRecord);
/*     */   }
/*     */   
/*     */   private static void clearPendingSend(Integer mailboxId, Pair<String, ItemId> sendRecord) {
/* 342 */     if (sendRecord != null) {
/* 343 */       synchronized (sSentTokens) {
/* 344 */         ((List)sSentTokens.get(mailboxId)).remove(sendRecord);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   private void deleteDraft(ItemId iidDraft, OperationContext octxt, Mailbox localMbox, ZimbraSoapContext zsc)
/*     */   {
/*     */     try {
/* 352 */       if (iidDraft.belongsTo(localMbox)) {
/* 353 */         localMbox.delete(octxt, iidDraft.getId(), MailItem.Type.MESSAGE);
/* 354 */       } else if (iidDraft.isLocal()) {
/* 355 */         Mailbox ownerMbox = MailboxManager.getInstance().getMailboxByAccountId(iidDraft.getAccountId());
/* 356 */         ownerMbox.delete(octxt, iidDraft.getId(), MailItem.Type.MESSAGE);
/*     */       } else {
/* 358 */         Account target = Provisioning.getInstance().get(Key.AccountBy.id, iidDraft.getAccountId());
/* 359 */         AuthToken at = AuthToken.getCsrfUnsecuredAuthToken(zsc.getAuthToken());
/* 360 */         ZAuthToken zat = at.getProxyAuthToken() == null ? at.toZAuthToken() : new ZAuthToken(at.getProxyAuthToken());
/* 361 */         ZMailbox.Options zoptions = new ZMailbox.Options(zat, AccountUtil.getSoapUri(target));
/* 362 */         zoptions.setNoSession(true);
/* 363 */         zoptions.setTargetAccount(target.getId()).setTargetAccountBy(Key.AccountBy.id);
/* 364 */         ZMailbox.getMailbox(zoptions).deleteMessage(iidDraft.toString());
/*     */       }
/*     */     }
/*     */     catch (ServiceException e) {
/* 368 */       ZimbraLog.soap.info("failed to delete draft after message send: %s", new Object[] { iidDraft });
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   private static class OutlookICalendarFixupMimeVisitor
/*     */     extends MimeVisitor
/*     */   {
/*     */     private boolean needFixup;
/*     */     
/*     */     private boolean isCalendarForward;
/*     */     
/*     */     private boolean isCalendarMessage;
/*     */     
/*     */     private final Account mAccount;
/*     */     
/*     */     private final Mailbox mMailbox;
/*     */     
/*     */     private int mMsgDepth;
/*     */     
/*     */     private String[] mFromEmails;
/*     */     
/*     */     private String mSentBy;
/*     */     
/*     */     private final String mDefaultCharset;
/* 393 */     private Invite origInvite = null;
/*     */     
/*     */     static class ICalendarModificationCallback implements MimeVisitor.ModificationCallback {
/*     */       private boolean mWouldModify;
/*     */       
/*     */       public boolean wouldCauseModification() {
/* 399 */         return this.mWouldModify;
/*     */       }
/*     */       
/*     */       public boolean onModification()
/*     */       {
/* 404 */         this.mWouldModify = true;
/* 405 */         return false;
/*     */       }
/*     */     }
/*     */     
/*     */     OutlookICalendarFixupMimeVisitor(Account acct, Mailbox mbox) {
/* 410 */       this.mAccount = acct;
/* 411 */       this.mMailbox = mbox;
/* 412 */       this.mMsgDepth = 0;
/* 413 */       this.mDefaultCharset = (acct == null ? null : acct.getPrefMailDefaultCharset());
/*     */     }
/*     */     
/*     */     public OutlookICalendarFixupMimeVisitor needFixup(boolean fixup) {
/* 417 */       this.needFixup = fixup;
/* 418 */       return this;
/*     */     }
/*     */     
/*     */     public OutlookICalendarFixupMimeVisitor setIsCalendarForward(boolean forward) {
/* 422 */       this.isCalendarForward = forward;
/* 423 */       return this;
/*     */     }
/*     */     
/*     */     public boolean isCalendarMessage() {
/* 427 */       return this.isCalendarMessage;
/*     */     }
/*     */     
/*     */     public Invite getOriginalInvite() {
/* 431 */       return this.origInvite;
/*     */     }
/*     */     
/*     */     protected boolean visitMessage(MimeMessage mm, MimeVisitor.VisitPhase visitKind) throws MessagingException {
/* 435 */       boolean modified = false;
/* 436 */       if (MimeVisitor.VisitPhase.VISIT_BEGIN.equals(visitKind)) {
/* 437 */         this.mMsgDepth += 1;
/* 438 */         if ((this.mMsgDepth == 1) && (this.needFixup)) {
/* 439 */           Address[] fromAddrs = mm.getFrom();
/* 440 */           Address senderAddr = mm.getSender();
/* 441 */           if ((senderAddr != null) && (fromAddrs != null))
/*     */           {
/* 443 */             for (Address from : fromAddrs) {
/* 444 */               if (from.equals(senderAddr)) {
/* 445 */                 return false;
/*     */               }
/*     */             }
/* 448 */             if (!(senderAddr instanceof InternetAddress))
/* 449 */               return false;
/* 450 */             String sender = ((InternetAddress)senderAddr).getAddress();
/* 451 */             if (sender == null) {
/* 452 */               return false;
/*     */             }
/* 454 */             String[] froms = new String[fromAddrs.length];
/* 455 */             for (int i = 0; i < fromAddrs.length; i++) {
/* 456 */               Address fromAddr = fromAddrs[i];
/* 457 */               if (fromAddr == null)
/* 458 */                 return false;
/* 459 */               if (!(fromAddr instanceof InternetAddress))
/* 460 */                 return false;
/* 461 */               String from = ((InternetAddress)fromAddr).getAddress();
/* 462 */               if (from == null)
/* 463 */                 return false;
/* 464 */               froms[i] = ("MAILTO:" + from);
/*     */             }
/*     */             
/* 467 */             this.mFromEmails = froms;
/* 468 */             this.mSentBy = ("MAILTO:" + sender);
/*     */             
/*     */ 
/* 471 */             mm.setReplyTo(new Address[] { senderAddr });
/* 472 */             modified = true;
/*     */           }
/*     */         }
/* 475 */       } else if (MimeVisitor.VisitPhase.VISIT_END.equals(visitKind)) {
/* 476 */         this.mMsgDepth -= 1;
/*     */       }
/*     */       
/* 479 */       return modified;
/*     */     }
/*     */     
/*     */     protected boolean visitMultipart(MimeMultipart mp, MimeVisitor.VisitPhase visitKind) {
/* 483 */       return false;
/*     */     }
/*     */     
/*     */     protected boolean visitBodyPart(MimeBodyPart bp) throws MessagingException
/*     */     {
/* 488 */       if (this.mMsgDepth != 1) {
/* 489 */         return false;
/*     */       }
/* 491 */       boolean modified = false;
/*     */       
/* 493 */       String ct = Mime.getContentType(bp);
/* 494 */       if ("text/calendar".compareToIgnoreCase(ct) != 0) {
/* 495 */         return false;
/*     */       }
/*     */       
/* 498 */       InputStream is = null;
/*     */       ZCalendar.ZVCalendar ical;
/* 500 */       try { DataSource source = bp.getDataHandler().getDataSource();
/* 501 */         is = source.getInputStream();
/* 502 */         String ctHdr = source.getContentType();
/* 503 */         String methodParam = new ContentType(ctHdr).getParameter("method");
/* 504 */         boolean bool1; if ((methodParam == null) || (methodParam.trim().isEmpty()))
/*     */         {
/* 506 */           return false;
/*     */         }
/* 508 */         this.isCalendarMessage = true;
/*     */         
/* 510 */         if ((!this.needFixup) && (!this.isCalendarForward)) {
/* 511 */           return false;
/*     */         }
/* 513 */         String charset = this.mDefaultCharset;
/* 514 */         String cs = Mime.getCharset(ctHdr);
/* 515 */         if (cs != null)
/* 516 */           charset = cs;
/* 517 */         ical = ZCalendar.ZCalendarBuilder.build(is, charset);
/*     */         List<Invite> inviteList;
/* 519 */         if (this.isCalendarForward)
/*     */         {
/* 521 */           inviteList = Invite.createFromCalendar(this.mAccount, null, ical, false);
/* 522 */           Invite defInvite = null;
/* 523 */           for (Invite cur : inviteList) {
/* 524 */             if (!cur.hasRecurId()) {
/* 525 */               defInvite = cur;
/* 526 */               break;
/*     */             }
/* 528 */             if (defInvite == null)
/* 529 */               defInvite = cur;
/*     */           }
/* 531 */           this.origInvite = defInvite;
/*     */         }
/*     */         
/* 534 */         if (!this.needFixup) {
/* 535 */           return 0;
/*     */         }
/*     */       } catch (Exception e) {
/* 538 */         throw new MessagingException("Unable to parse iCalendar part: " + e.getMessage(), e);
/*     */       } finally {
/* 540 */         ByteUtil.closeStream(is);
/*     */       }
/*     */       
/* 543 */       String method = ical.getPropVal(ZCalendar.ICalTok.METHOD, ZCalendar.ICalTok.REQUEST.toString());
/* 544 */       boolean isReply = method.equalsIgnoreCase(ZCalendar.ICalTok.REPLY.toString());
/*     */       
/* 546 */       if (!isReply) {
/* 547 */         modified = fixupRequest(ical);
/*     */       } else {
/*     */         try {
/* 550 */           modified = fixupReply(ical);
/*     */         } catch (ServiceException e) {
/* 552 */           SendMsg.LOG.warn("Unable perform fixup of calendar reply from Outlook for mailbox " + this.mMailbox.getId() + "; ignoring error", e);
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 557 */       if (modified)
/*     */       {
/* 559 */         if ((this.mCallback != null) && (!this.mCallback.onModification())) {
/* 560 */           return false;
/*     */         }
/* 562 */         String filename = bp.getFileName();
/* 563 */         if (filename == null)
/* 564 */           filename = "meeting.ics";
/* 565 */         bp.setDataHandler(new DataHandler(new CalendarDataSource(ical, filename)));
/*     */       }
/*     */       
/* 568 */       return modified;
/*     */     }
/*     */     
/*     */     private boolean fixupRequest(ZCalendar.ZVCalendar ical) {
/* 572 */       boolean modified = false;
/* 573 */       for (Iterator<ZCalendar.ZComponent> compIter = ical.getComponentIterator(); compIter.hasNext();) {
/* 574 */         ZCalendar.ZComponent comp = (ZCalendar.ZComponent)compIter.next();
/* 575 */         ZCalendar.ICalTok compType = comp.getTok();
/* 576 */         if ((ZCalendar.ICalTok.VEVENT.equals(compType)) || (ZCalendar.ICalTok.VTODO.equals(compType)))
/*     */         {
/*     */ 
/* 579 */           boolean isSeries = false;
/* 580 */           for (Iterator<ZCalendar.ZProperty> propIter = comp.getPropertyIterator(); propIter.hasNext();) {
/* 581 */             ZCalendar.ZProperty prop = (ZCalendar.ZProperty)propIter.next();
/* 582 */             ZCalendar.ICalTok token = prop.getToken();
/* 583 */             if (token != null)
/*     */             {
/* 585 */               switch (SendMsg.2.$SwitchMap$com$zimbra$common$calendar$ZCalendar$ICalTok[token.ordinal()]) {
/*     */               case 1: 
/*     */               case 2: 
/* 588 */                 if ((this.mFromEmails != null) && (this.mSentBy != null)) {
/* 589 */                   String addr = prop.getValue();
/* 590 */                   if (addressMatchesFrom(addr)) {
/* 591 */                     ZCalendar.ZParameter sentBy = prop.getParameter(ZCalendar.ICalTok.SENT_BY);
/* 592 */                     if (sentBy == null) {
/* 593 */                       prop.addParameter(new ZCalendar.ZParameter(ZCalendar.ICalTok.SENT_BY, this.mSentBy));
/* 594 */                       modified = true;
/* 595 */                       ZimbraLog.calendar.info("Fixed up " + token + " (" + addr + ") by adding SENT-BY=" + this.mSentBy);
/*     */                     }
/*     */                   }
/*     */                 }
/*     */                 
/* 600 */                 break;
/*     */               
/*     */               case 3: 
/* 603 */                 isSeries = true;
/*     */               }
/*     */             }
/*     */           }
/* 607 */           if (isSeries) {
/* 608 */             comp.addProperty(new ZCalendar.ZProperty(ZCalendar.ICalTok.X_ZIMBRA_DISCARD_EXCEPTIONS, true));
/* 609 */             modified = true;
/*     */           }
/*     */         } }
/* 612 */       return modified;
/*     */     }
/*     */     
/*     */ 
/*     */     private boolean fixupReply(ZCalendar.ZVCalendar ical)
/*     */       throws ServiceException
/*     */     {
/* 619 */       Map<String, ZCalendar.ZProperty> uidToOrganizer = new HashMap();
/*     */       
/*     */ 
/*     */ 
/* 623 */       List<Invite> replyInvs = Invite.createFromCalendar(this.mAccount, null, ical, false);
/* 624 */       for (Invite replyInv : replyInvs) {
/* 625 */         ZOrganizer replyOrg = replyInv.getOrganizer();
/*     */         
/*     */ 
/* 628 */         if ((replyOrg == null) || (!replyOrg.hasSentBy()))
/*     */         {
/*     */ 
/* 631 */           String uid = replyInv.getUid();
/* 632 */           this.mMailbox.lock.lock();
/*     */           try {
/* 634 */             CalendarItem calItem = this.mMailbox.getCalendarItemByUid(null, uid);
/* 635 */             if (calItem != null) {
/* 636 */               RecurId rid = replyInv.getRecurId();
/* 637 */               Invite inv = calItem.getInvite(rid);
/* 638 */               if ((inv == null) && (rid != null)) {
/* 639 */                 inv = calItem.getInvite((RecurId)null);
/*     */               }
/* 641 */               if (inv != null) {
/* 642 */                 ZOrganizer org = inv.getOrganizer();
/* 643 */                 if (org != null) {
/* 644 */                   ZCalendar.ZProperty orgProp = org.toProperty();
/* 645 */                   if (replyOrg == null)
/*     */                   {
/* 647 */                     uidToOrganizer.put(uid, orgProp);
/*     */                   }
/*     */                   else
/*     */                   {
/* 651 */                     String replyOrgAddr = replyOrg.getAddress();
/* 652 */                     String orgAddr = org.getAddress();
/* 653 */                     if ((org.hasSentBy()) || ((orgAddr != null) && (!orgAddr.equalsIgnoreCase(replyOrgAddr))))
/*     */                     {
/* 655 */                       uidToOrganizer.put(uid, orgProp);
/*     */                     }
/*     */                     
/*     */                   }
/*     */                 }
/*     */               }
/*     */             }
/*     */           }
/*     */           finally
/*     */           {
/* 665 */             this.mMailbox.lock.release();
/*     */           }
/*     */         }
/*     */       }
/* 669 */       if (uidToOrganizer.isEmpty()) {
/* 670 */         return false;
/*     */       }
/*     */       
/* 673 */       for (Iterator<ZCalendar.ZComponent> compIter = ical.getComponentIterator(); compIter.hasNext();) {
/* 674 */         ZCalendar.ZComponent comp = (ZCalendar.ZComponent)compIter.next();
/* 675 */         ZCalendar.ICalTok compType = comp.getTok();
/* 676 */         if ((ZCalendar.ICalTok.VEVENT.equals(compType)) || (ZCalendar.ICalTok.VTODO.equals(compType)))
/*     */         {
/*     */ 
/* 679 */           String uid = comp.getPropVal(ZCalendar.ICalTok.UID, null);
/* 680 */           ZCalendar.ZProperty fixedOrganizer = (ZCalendar.ZProperty)uidToOrganizer.get(uid);
/* 681 */           if (fixedOrganizer != null)
/*     */           {
/*     */ 
/*     */ 
/* 685 */             for (Iterator<ZCalendar.ZProperty> propIter = comp.getPropertyIterator(); propIter.hasNext();) {
/* 686 */               ZCalendar.ZProperty prop = (ZCalendar.ZProperty)propIter.next();
/* 687 */               ZCalendar.ICalTok token = prop.getToken();
/* 688 */               if (ZCalendar.ICalTok.ORGANIZER.equals(token)) {
/* 689 */                 propIter.remove();
/* 690 */                 break;
/*     */               }
/*     */             }
/*     */             
/*     */ 
/* 695 */             comp.addProperty(fixedOrganizer);
/* 696 */             ZimbraLog.calendar.info("Fixed up ORGANIZER in a REPLY from ZCO");
/*     */           } } }
/* 698 */       return true;
/*     */     }
/*     */     
/*     */     private boolean addressMatchesFrom(String addr) {
/* 702 */       if (addr == null)
/* 703 */         return false;
/* 704 */       for (String from : this.mFromEmails) {
/* 705 */         if (from.compareToIgnoreCase(addr) == 0)
/* 706 */           return true;
/*     */       }
/* 708 */       return false;
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/service/mail/SendMsg.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */